package jmine.tec.persist.hibernate.merger;

import java.io.Serializable;
import java.lang.reflect.Constructor;

import jmine.tec.persist.PersistMessages;

import org.hibernate.SessionFactory;

import bancosys.tec.persist.Persistable;
import bancosys.tec.persist.controller.PersistenceEnabledController;
import bancosys.tec.persist.exception.PersistenceException;

/**
 * Carregador de entidades por classe e id.
 * 
 * @author wellington.santos
 * @created May 30, 2012
 */
public class FastEntityLoader implements EntityLoader {

    private SessionFactory sessionFactory;

    private PersistenceEnabledController controller;

    /**
     * {@inheritDoc}
     * 
     * @return {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public <T> T get(Class<T> entityClass, Serializable id) {
        Object o = this.sessionFactory.getCurrentSession().get(entityClass, id);
        return o == null ? this.create(entityClass) : (T) o;
    }

    /**
     * {@inheritDoc}
     * 
     * @return {@inheritDoc}
     */
    public <T> T create(Class<T> entityClass) {
        T result;
        try {
            Constructor<T> ctor = entityClass.getDeclaredConstructor();
            if (!ctor.isAccessible()) {
                ctor.setAccessible(true);
            }
            result = ctor.newInstance();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new PersistenceException(PersistMessages.UNABLE_TO_INSTANTIATE_BEAN.create(entityClass.getName()), e);
        }
        if (result instanceof Persistable) {
            Persistable p = (Persistable) result;
            p.setController(this.controller);
            p.setDirty(true);
        }
        return result;
    }

    /**
     * @return sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    /**
     * @param sessionFactory sessionFactory
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * @return controller
     */
    public PersistenceEnabledController getController() {
        return this.controller;
    }

    /**
     * @param controller controller
     */
    public void setController(PersistenceEnabledController controller) {
        this.controller = controller;
    }

}
